/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：呼叫中心-通用处理层-任务调度
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taiping.cc.job.manager.transaction;

import com.taiping.cc.job.dataobject.HttpParamConfigDO;
import com.taiping.cc.job.dataobject.HttpRequestConfigDO;
import com.taiping.cc.job.dataobject.HttpResponseConfigDO;
import com.taiping.cc.job.base.BaseService;
import com.taipingframework.utility.exception.ManagerException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author 周孝兵
 * @since 2022-12-14
 * <p>
 * 将业务对象或者数据传输对象转换为数据对象之后，持久化到数据库。
 * 个人想法：在高并发场景下，网络服务持续向数据库进行写操作，数据库服务器的压力会变得很大，
 * 此时为了降低数据库服务器的负荷，同时也为了提高网络服务的吞吐量，在manager层可以选择先将写入
 * 到数据库的数据对象直接在redis服务器进行缓存，同时向RocketMQ消息队列发布消息(redis-key)，
 * 再通过在当前服务实例上的RocketMQ消费者消费消息，将数据对象异步持久化到数据库。
 * <p>
 * 在这个过程中需要解决以下两个问题：
 * 1、集群环境下RocketMQ消费者`幂等性`问题需要解决，避免重复消费，使用分布式锁；
 * 2、redis缓存数据与数据库中的数据，需要保证最终一致性。当RocketMQ消费者对数据库进行数据持久化操作失败时，
 * (例如锁表，唯一约束冲突，数据库服务器意外宕机等等)，为了保证数据不丢失，可以选择将数据报文存放在死信队列，
 * 或者将数据报文临时持久化到别的数据库服务器，后期通过数据补偿机制找回丢失的数据。
 * 3、网络服务查询数据时，应该先读取本地缓存(ehcache)，一级缓存不存在时，再读取二级缓存(redis)，
 * 若二级缓存也不存在，才会去数据库进行读取操作。
 */
@Service
public class HttpServiceTransaction extends BaseService {

    /**
     * 网络服务 持久化 到数据库，此处进行事务控制
     */
    @Transactional
    public void saveHttpServiceConfig(HttpRequestConfigDO requestConfig, HttpResponseConfigDO responseConfig, List<HttpParamConfigDO> paramConfigList) throws ManagerException {
        try {
            httpRequestConfigDAO.saveOrUpdate(requestConfig);
            httpResponseConfigDAO.saveOrUpdate(responseConfig);
            httpParamConfigDAO.saveOrUpdateList(paramConfigList);
        } catch (Exception e) {
            throw new ManagerException(e);
        }
    }

}
